#include <stdio.h>



#include <strings.h>



#include <stdlib.h>



#include "TableSym.h"











int address = -1;



int numFct = -1;



int max = 0;



int nbArg = 0;



int nbVar = 0;















//créer un noeud pour une nouvelle fonction



FCTSYM createSTNodeFct()



{



    FCTSYM node = (FCTSYM) malloc(sizeof(FCTSYMNODE));



    if (node == NULL) {



	fprintf(stderr, "KO\n");



	printf("ERROR : cannot malloc in createSTNodeFct()\n");



	exit(1);



    }

	else
	return node;



}











//créer un noeud pour une nouvelle variable



VARSYM createSTNodeVar()



{



    VARSYM node = (VARSYM) malloc(sizeof(VARSYMNODE));



    if (node == NULL) {



	fprintf(stderr, "KO\n");



	printf("ERROR : cannot malloc in createSTNodeFct()\n");



	exit(1);



    }



    



    return node;



}











//Créer la table des symboles (créer le premier noeud de fonction)



FCTSYM createSymTable()



{



    FCTSYM symFct = (FCTSYM) createSTNodeFct(NULL, NULL, "Root", NULL, 0, -1);



    return symFct;



}











//ajouter une fonction à la table des symboles



FCTSYM addFctToSymTable(FCTSYM parentFct, TREE locationOnTree,



			char *name, char *retType, int isMain, int level)



{



    FCTSYM node;



    node = createSTNodeFct();


	if (parentFct != NULL)	//cas d'une fonction imbriquée dans une autre



    {



	node->parentFct = parentFct;



	node->next = parentFct->childFct;



	node->prev = NULL;



	node->childFct = NULL;



	if (parentFct->childFct != NULL)	//si parentFct est la racine, son child est NULL



	{



	    parentFct->childFct->prev = node;



	}



	parentFct->childFct = node;	//on ajoute le noeud aux fils de la fonction parente



    }







    else			//pour la première cellule (racine)



    {



	node->next = NULL;



	node->prev = NULL;



	node->parentFct = NULL;



	node->childFct = NULL;



    }



    node->name = name;



    node->retType = retType;



    node->level = level;



    node->numFct = numFct;



    node->locationOnTree = locationOnTree;



    node->isMain = isMain;



    node->nextVar = NULL;



    return node;



}











//ajouter une variable à la table des symboles



VARSYM addVarToSymTable(FCTSYM fct, TREE locationOnTree, char *name, char *type, int level, int varMode)



{



    VARSYM node = createSTNodeVar();


	node->name = name;



    node->type = type;



    node->varMode = varMode;



    node->fct = fct;



    node->level = level;



    if (fct->nextVar != NULL) {



	node->next = fct->nextVar;



	fct->nextVar->prev = node;



    }







    else {



	node->next = NULL;



    }



    fct->nextVar = node;



    node->prev = NULL;



    node->locationOnTree = locationOnTree;



    node->address = address;


    return node;



}











//chercher les variables



void fillSymTableWithVariable(FCTSYM fct, TREE tree, int level, char *type)



{



    if (tree != NULL) {







	//chercher les variables qui se trouvent dans la partie declarations



	if (tree->type == AT_DECL) {



	    fillSymTableWithVariable(fct, tree->left, level, NULL);



	}



	if (tree->type == AT_ILISTDECL) {



	    fillSymTableWithVariable(fct, tree->left, level, NULL);



	    fillSymTableWithVariable(fct, tree->middle, level, NULL);



	}



	if (tree->type == AT_INT) {



	    fillSymTableWithVariable(fct, tree->left, level, "int");



	}



	if (tree->type == AT_BOOL) {



	    fillSymTableWithVariable(fct, tree->left, level, "bool");



	}



	if (tree->type == AT_MATRIX) {



	    fillSymTableWithVariable(fct, tree->left, level, "matrix");



	}



	if (tree->type == AT_LISTVAR) {



	    fillSymTableWithVariable(fct, tree->left, level, type);



	    fillSymTableWithVariable(fct, tree->middle, level, type);



	}



	if (tree->type == AT_ID) {



	    if (!alreadyIsSymbolVar(fct, tree->name))	//on ajoute la variable uniquement si il n'existe pas d'autre variable ayant le même nom dans la fonction



	    {



		max++;



		address++;



		VARSYM var;



		var =



		    addVarToSymTable(fct, tree, tree->name, type, level,



				     -1);



		nbVar++;



		fct->nbVar = nbVar;



	    }



	}



    }



}











//chercher les arguments d'une fonction



void fillSymTableWithArgument(FCTSYM fct, TREE tree, int level,



			      char *type, int varMode)



{



    if (tree != NULL) {



	if (tree->type == AT_LISTARG) {



	    fillSymTableWithArgument(fct, tree->left, level, type,



				     varMode);



	    if (tree->middle != NULL) {



		fillSymTableWithArgument(fct, tree->middle, level,



					 type, varMode);



	    }



	}



	if (tree->type == AT_ARGVARINT) {



	    fillSymTableWithArgument(fct, tree->left, level, "int", 1);



	}



	if (tree->type == AT_ARGINT) {



	    fillSymTableWithArgument(fct, tree->left, level, "int", 0);



	}



	if (tree->type == AT_ARGVARBOOL) {



	    fillSymTableWithArgument(fct, tree->left, level, "bool", 1);



	}



	if (tree->type == AT_ARGBOOL) {



	    fillSymTableWithArgument(fct, tree->left, level, "bool", 0);



	}



	if (tree->type == AT_ARGVARMATRIX) {



	    fillSymTableWithArgument(fct, tree->left, level, "matrix", 1);



	}



	if (tree->type == AT_ARGMATRIX) {



	    fillSymTableWithArgument(fct, tree->left, level, "matrix", 0);



	}



	if (tree->type == AT_ID) {



	    if (!alreadyIsSymbolVar(fct, tree->name))	//on ajoute la variable (argument) uniquement si il n'existe pas d'autre variable ayant le même nom dans la fonction



	    {



		VARSYM arg;



		address++;



		arg =



		    addVarToSymTable(fct, tree, tree->name, type, level,



				     varMode);



		nbArg++;



		fct->nbArguments = nbArg;



	    }



	}



    }



}











//pour remplir la table des symboles avec des fonctions (appel sur root)



void fillSymTableWithFonction(FCTSYM lastAddedFct, TREE tree, int level,



			      char *nameMain)



{



    if (tree->type == AT_ROOT) {



	level++;



	fillSymTableWithFonction(lastAddedFct, tree->middle, level,



				 nameMain);



    }



    if (tree->type == AT_LISTFCT) {



	fillSymTableWithFonction(lastAddedFct, tree->left, level,



				 nameMain);



	fillSymTableWithFonction(lastAddedFct, tree->middle, level,



				 nameMain);



    }



    if (tree->type == AT_FCT) {



	FCTSYM newFct;



	if (lastAddedFct == NULL) {



	    printf



		("lose: fonction déjà présente!!!!!!!!!!!!!!!!!!!!!!!!!\n");



	}







	else {



	    if ((level == 1) && (strcmp(tree->name, nameMain) == 0))	// trouver la fonction Main



	    {



		if (!alreadyIsSymbolFctInParentFct(lastAddedFct, tree->name))	//vérifier si pas de fonction du même nom déjà présente



		{



		    numFct++;



		    newFct =



			addFctToSymTable(lastAddedFct, tree, tree->name,



					 tree->middle->name, 1, level);



		}



	    }







	    else {



		if (!alreadyIsSymbolFctInParentFct(lastAddedFct, tree->name))	//vérifier si pas de fonction du même nom déjà présente



		{



		    numFct++;



		    newFct =



			addFctToSymTable(lastAddedFct, tree, tree->name,



					 tree->middle->name, 0, level);



		}



	    }



	    fillSymTableWithFonction(newFct, tree->right, level, nameMain);	//pour les fonctions a un niveau encore inferieur



	    address = -1;



	    fillSymTableWithVariable(newFct, tree->right, level, NULL);	//la partie declaration d'une fonction se trouve dans le noeud de droite



	    fillSymTableWithArgument(newFct, tree->left, level, NULL, 0);



	    nbArg = 0;



	    nbVar = 0;



	}



    }



    if (tree->type == AT_DECL) {



	level++;



	if (tree->left != NULL) {



	    fillSymTableWithFonction(lastAddedFct, tree->left, level,



				     nameMain);



	}



    }



    if (tree->type == AT_ILISTDECL) {



	if (tree->left != NULL) {



	    fillSymTableWithFonction(lastAddedFct, tree->left, level,



				     nameMain);



	}



	if (tree->middle != NULL) {



	    fillSymTableWithFonction(lastAddedFct, tree->middle, level,



				     nameMain);



	}



    }



}







int alreadyIsSymbolFctInParentFct(FCTSYM symFct, char *name)



{



    return (searchFctAtParentFct(symFct, name) == NULL) ? 0 : 1;	//on vérifie si une fonction de même nom est déjà présente dans la même fonction parente



}







int alreadyIsSymbolVar(FCTSYM symFct, char *name)



{



    return (searchVarAtFct(symFct, name) == NULL) ? 0 : 1;	//on vérifie si une variable de même nom est déjà présente uniquement dans la même fonction



}











//afficher la liste des variable d'une fonction



void printSymbolVar(VARSYM varSym)



{



    if (varSym != NULL) {



	if (varSym->varMode == -1) {



	    printf



		("; Variable: [%p] name=%s ,level=%d, fonction englobante=%s, type=%s, adresse locale=%d, locationOnTree=	[%p], next=%p, prev=%p,  \n",



		 varSym, varSym->name, varSym->level,



		 varSym->fct->name, varSym->type, varSym->address,



		 varSym->locationOnTree, varSym->next, varSym->prev);



	}







	else {



	    printf



		("; Argument: [%p] name=%s ,level=%d, fonction englobante=%s, type=%s, adresse locale=%d, locationOnTree=	[%p], next=%p, prev=%p, varMode=%d \n",



		 varSym, varSym->name, varSym->level,



		 varSym->fct->name, varSym->type, varSym->address,



		 varSym->locationOnTree, varSym->next, varSym->prev,



		 varSym->varMode);



	}



	printSymbolVar(varSym->next);



    }



}











//afficher la table des symbole complète



void printSymbolTable(FCTSYM symFct)



{



    if (symFct != NULL) {



	printf



	    ("; Fonction: [%p] name= %s , level=%d, numFct=%d, nbArgs=%d, nbVar = %d, locationOnTree=[%p], next=%p , prev=%p , child=%p , parent=%p, nextVar = %p \n",



	     symFct, symFct->name, symFct->level, symFct->numFct,



	     symFct->nbArguments, symFct->nbVar, symFct->locationOnTree,



	     symFct->next, symFct->prev, symFct->childFct,



	     symFct->parentFct, symFct->nextVar);



	if (symFct->nextVar != NULL) {



	    printSymbolVar(symFct->nextVar);



	}



	printSymbolTable(symFct->childFct);



	printSymbolTable(symFct->next);



    }



}











//libérer l'espace des noeuds de fonctions



void freeSymTableFct(FCTSYM fctSym)



{



    if (fctSym != NULL) {



	if (fctSym->name != NULL)



	    free(fctSym->name);



	if (fctSym->retType != NULL)



	    free(fctSym->retType);



	freeSymTableFct(fctSym->next);



	freeSymTableVar(fctSym->nextVar);



	free(fctSym);



    }



}











//libérer l'espace des noeuds de variables



void freeSymTableVar(VARSYM varSym)



{



    if (varSym != NULL) {



	if (varSym->name != NULL)



	    free(varSym->name);



	freeSymTableVar(varSym->next);



	free(varSym);



    }



}







VARSYM searchVarAtFct(FCTSYM fct, char *name)



{



    VARSYM p;



    p = fct->nextVar;



    while (p != NULL) {



	if (strcmp(p->name, name) == 0) {



	    return p;



	}







	else {



	    p = p->next;



	}



    }



    return NULL;		// la variable 'name' n'est pas déclarée dans fct



}



VARSYM searchVarAtFctByPos(FCTSYM fct, int pos)

{

	VARSYM p;

	p = fct->nextVar;

	while(pos>1)

	{

	p = p->next;

	pos--;

	}

	return p;



}







FCTSYM searchFctAtParentFct(FCTSYM fct, char *name)



{



    FCTSYM f;



    f = fct->childFct;



    while (f != NULL) {



	if (strcmp(f->name, name) == 0) {



	    return f;



	}







	else {



	    f = f->next;



	}



    }



    return NULL;		// la variable 'name' n'est pas déclarée dans fct



}







void printSymTableForDia(FCTSYM fct, int nb)



{







}






